package 网络编程;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;

/*
public class 模拟ClientTcp {
	public static void main(String[] args) {
      System.out.println("客户端......");
      try (Socket socket= new Socket("localhost",6666);
          DataInputStream dis = new DataInputStream(socket.getInputStream());
          DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
      	Scanner input=new Scanner(System.in);
          while(true) {
              System.out.print("请输入信息：");
              dos.writeUTF(input.next());
              dos.flush();

              String receive = dis.readUTF();
              System.out.println("来自服务端的数据：" + receive);
          }
      } catch (IOException e) {
      	System.out.println("客户端访问服务端出错！");
          e.printStackTrace();
      }

	}
}
*/
public class 模拟ClientTcp {
    public static void main(String[] args) throws IOException {
        Socket sock = new Socket("localhost", 6663); // 连接指定服务器和端口
        try (InputStream input = sock.getInputStream()) {
            try (OutputStream output = sock.getOutputStream()) {
                handle(input, output);
            }
        }
        sock.close();
        System.out.println("disconnected.");
    }

    private static void handle(InputStream input, OutputStream output) throws IOException {
        var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
        var reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
        Scanner scanner = new Scanner(System.in);
        System.out.println("[server] " + reader.readLine());
        for (;;) {
            System.out.print(">>> "); // 打印提示
            String s = scanner.nextLine(); // 读取一行输入
            writer.write(s);
            writer.newLine();
            writer.flush();
            String resp = reader.readLine();// 获取Service端流信息
            System.out.println("<<< " + resp);
            if (resp.equals("bye")) {
                break;
            }
        }
    }
}
/*
 * 客户端程序通过：
 * 
 * Socket sock = new Socket("localhost", 6666);
 * 或：
 * Socket sock = new Socket("127.0.0.1", 6666);
 * 连接到服务器端，注意上述代码的服务器地址是"localhost"，表示本机地址，端口号是6666。如果连接成功，将返回一个Socket实例，用于
 * 后续通信。
 * 
 * Socket流
 * 当Socket连接创建成功后，无论是服务器端，还是客户端，我们都使用Socket实例进行网络通信。因为TCP是一种基于流的协议，因此，Java标
 * 准库使用InputStream和OutputStream来封装Socket的数据流，这样我们使用Socket的流，和普通IO流类似：
 * 
 * // 用于读取网络数据:
 * InputStream in = sock.getInputStream();
 * // 用于写入网络数据:
 * OutputStream out = sock.getOutputStream();
 * 最后我们重点来看看，为什么写入网络数据时，要调用flush()方法。
 * 
 * 如果不调用flush()，我们很可能会发现，客户端和服务器都收不到数据，这并不是Java标准库的设计问题，而是我们以流的形式写入数据的时
 * 候，并不是一写入就立刻发送到网络，而是先写入内存缓冲区，直到缓冲区满了以后，才会一次性真正发送到网络，这样设计的目的是为了提高传输效
 * 率。如果缓冲区的数据很少，而我们又想强制把这些数据发送到网络，就必须调用flush()强制把缓冲区数据发送出去。
 */